// Copyright  2012 Petr TALLA. [petr.talla@gmail.com]
// This file is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY;  without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
// [http://www.gnu.org/copyleft/lesser.html]
//=============================================================================

package tc.crase.save;

import java.awt.geom.Point2D;
import java.io.File;

import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.node.ArrayNode;
import org.codehaus.jackson.node.ObjectNode;
import org.codehaus.jackson.node.TextNode;

import tc.crase.db.XattrGIT;
import tc.crase.db.XattrGRP;
import tc.crase.db.XattrGXY;
import tc.crase.db.XattrLNK;
import tc.crase.db.XattrSTR;
import tc.crase.db.XattrTPE;
import tc.crase.db.XattrURL;
import tc.crase.db.Xdb;
import tc.crase.db.Xobject;
import tc.crase.sys.XobjectEx;

public class XdbLoadDb {
	ObjectNode  jsonRoot;
	Xdb xdb;
	public String status = new String("");
	
	public XdbLoadDb(Xdb xdb) {
		this.xdb = xdb;
		reset();
	}
	
	public boolean load(File file, boolean metaOnly) {
		if (file.canWrite() == false) {
			status = "Writing in file is not possible.";
			reset();
			return false;
		}
		
		if (metaOnly == false){
			xdb.fileName = file.toString();
		}
		
		ObjectMapper mapper = new ObjectMapper();
		
		try {
			jsonRoot = mapper.readValue(file, ObjectNode.class);
		}
		catch (Exception ee ) {
			status = "Error loading file." + ee.getMessage();
			reset();
			return false;
		}
		
		loadData(metaOnly);

		return true;
	}

	void reset() {
		jsonRoot = null;
	}
	
	public void loadData(boolean metaOnly) {
		if (metaOnly) return;
		loadObjects();
	}

	void loadObjects() {
		ArrayNode jsonArray = (ArrayNode)jsonRoot.get("objects");
		
		for ( int i = 0; i < jsonArray.size(); i++ )
		{	ObjectNode node = (ObjectNode)jsonArray.get(i);
			JsonNode nameNode = (TextNode)node.get("name");
			JsonNode idNode = node.get("id");
			
			//Xobject object = new Xobject();
			
			int id = -1;
			
			if (idNode != null) id = idNode.getValueAsInt(); 
			
			//xdb.add(object);
			Xobject object = xdb.createObject(id);
			
			ArrayNode attrs = (ArrayNode)node.get("attrs");
			XdbLoadDb.loadAttrs(attrs, object);
		}
	}

	
	static public void loadAttrs(ArrayNode jsonArray, Xobject parent) {
		for ( int i = 0; i < jsonArray.size(); i++ ) {
			ObjectNode node = (ObjectNode)jsonArray.get(i);
			JsonNode nameNode = (TextNode)node.get("name");
			String name = "";
			if (nameNode != null) if (nameNode.isTextual()) name = nameNode.getTextValue();
			
			JsonNode typeNode = (TextNode)node.get("type");
			String type = "";
			if (typeNode != null) if (typeNode.isTextual()) type = typeNode.getTextValue();
			
			if ("LNK".equals(type)) {
				loadAttrLNK(name, node, parent);
			}
			else if ("TPE".equals(type)) {
				loadAttrTPE(node, parent);
			}
			else if ("STR".equals(type)) {
				loadAttrSTR(node, parent);
			}
			else if ("GRP".equals(type)) {
				loadAttrGRP(node, parent);
			}
			else if ("GXY".equals(type)) {
				loadAttrGXY(node, parent);
			}
			else if ("URL".equals(type)) {
				loadAttrURL(node, parent);
			}
		}
	}
	
	static public void loadAttrGXY(JsonNode node, Xobject object) {
		int gid = node.get("gid").getValueAsInt();
		int id = node.get("id").getValueAsInt();
		double x = node.get("x").getValueAsDouble();
		double y = node.get("y").getValueAsDouble();
		
		String gurl = "";
		JsonNode gurlNode = (JsonNode)node.get("gurl");
		if (gurlNode != null) gurl = gurlNode.getTextValue();
		
		//if (id  < 1000) id += 1000;
		//if (gid < 2000) gid += 2000;
		
		XattrGXY gxy = new XattrGXY(id, gid, gurl, object, new Point2D.Double(x, y));
		object.attrAdd(gxy);
	}

	static public void loadAttrGRP(JsonNode node, Xobject object) {
		int id = node.get("id").getValueAsInt();
		
		//if (id < 2000) id += 2000;
		
		XattrGRP grp = new XattrGRP(id, object);
		object.attrAdd(grp);
		
		ArrayNode jsonItems = (ArrayNode)node.get("items");
		
		if (jsonItems != null) for(JsonNode item : jsonItems) {
			int iid = item.getValueAsInt();
			//if (iid < 1000) iid += 1000;  
			grp.add(iid, "");
		}
		
		ArrayNode jsonItems2 = (ArrayNode)node.get("items2");
		
		if (jsonItems2 != null) for(JsonNode item : jsonItems2) { 
			int iid = item.get("id").getValueAsInt();
			//if (iid < 1000) iid += 1000;
			String url = item.get("url").getValueAsText();
			grp.add(iid, url);
		}
	}

	static public void loadAttrLNK(String name, JsonNode node, Xobject object) {
		boolean first = node.get("first").getValueAsBoolean();
		int id = node.get("id").getValueAsInt();
		
		JsonNode oppositeIdNode = node.get("oppositeId");
		int oppositeId = oppositeIdNode.getValueAsInt();
		
		String oppositeUrl = "";
		JsonNode oppositeUrlNode = (JsonNode)node.get("oppositeUrl");
		if (oppositeUrlNode != null) oppositeUrl = oppositeUrlNode.getTextValue();
		
		new XattrLNK(name, object, id, oppositeId, oppositeUrl, first);
	}
	
	static public void loadAttrSTR(JsonNode node, Xobject object) {
		String name = node.get("name").getValueAsText();
		String value = node.get("value").getValueAsText();
		XattrSTR str = new XattrSTR(name, value);
		object.attrAdd(str);
	}
	
	static public void loadAttrURL(JsonNode node, Xobject object) {
		String name = node.get("name").getValueAsText();
		String value = node.get("value").getValueAsText();
		XattrURL str = new XattrURL(name, value);
		object.attrAdd(str);
	}

	static public void loadAttrTPE(JsonNode node, Xobject object) {
		JsonNode nodeId = node.get("id");
		if (nodeId == null) return;
		String id = nodeId.getValueAsText();
		XattrTPE tpe = new XattrTPE(id);
		object.attrAdd(tpe);
	}
}
